From 29849f56a45096f4408eeace311a49eca0765852 Mon Sep 17 00:00:00 2001 From: robertl Date: Wed, 23 Oct 2002 14:47:10 +0000 Subject: [PATCH] Better quadrant mapping for MS pushpin. Add README.psp. From Alex Mottram. --- README.psp | 85 +++++++++++++++++++++++ psp.c | 171 ++++++++++++++++++++++++++++++++++------------- reference/ps.psp | Bin 964 -> 964 bytes 3 files changed, 211 insertions(+), 45 deletions(-) create mode 100644 README.psp diff --git a/README.psp b/README.psp new file mode 100644 index 000000000..7a03a813e --- /dev/null +++ b/README.psp @@ -0,0 +1,85 @@ +Using gpsbabel to create MS 2002 Pushpin Files +---------------------------------------------- + +The standard S&T method: + 1. Create pushpins in S&T 2002 either by click-and-create or by importing + from a CSV format file (A header line helps greatly decrease the time + spent in the import data wizard). + 2. Select the map region you wish to create. + 3. Wait a couple of dozen minutes for the map to export. + 4. Copy map and corresponding .psp file to a folder on the mobile device. + 5. Open map in pocketstreets. + +The gpsbabel/psp method: + 1. Be sure you've already created the map/region. + (in this case, Lafayette.mps). + 2. Run gpsbabel with .psp output. + (i.e. gpsbabel -i geo -f geocaching.loc -o psp -F Lafayette.psp) + 3. Open map in pocketstreets. + +Notes in general: + o PocketStreets loads pushpins files with the same name as the MAP + being loaded. So if you have a map, "Lafayette.mps", the + corresponding set of pins should be called "Lafayette.psp". + These two files need to be in the same "folder" on the mobile + device in order for things to work properly (waah!). + + o Pocketstreets re-writes pushpin files every time you open and + close the map. Doing so sometimes re-sizes the pushpin files. + That's OK. + + o Pocketstreets won't choke on pushpins that are not for the map + being viewed, it simply "grays" them out in Pushpin Explorer. + This lets us make one HUGE pushpin file that covers dozens of + maps. + + +Example Usage: + o I get 2 files from geocaching.com on a regular basis, each + containing a couple-of-hundred waypoints. + + o I have a directory.. err.. folder on my hard drive located at + c:\makefiles. + + o In that directory, I keep a batch file called "makefiles.bat" that + looks like this: + + @echo off + + REM *** EXPERTGPS GPX FORMAT *** + REM *** NOTE THAT -x n IS NOT A STANDARD GPSBABEL FEATURE *** + gpsbabel -i geo -f 51.loc -f 61.loc -x n -o gpx -F e:\expertgps\geocaches.gpx + + REM *** FILES FOR MAGELLAN SD CARD *** + gpsbabel -i gpx -f e:\expertgps\geocaches.gpx -o magellan -F geocache.wpt + + REM *** BASE FILE FOR POCKETSTREETS PUSHPINS *** + REM *** NOTICE "-s" TO SYNTHESIZE SHORTNAMES *** + gpsbabel -s -i gpx -f e:\exertgps\geocaches.gpx -o psp -F geocache.psp + + REM *** MULTIPLY PUSHPINS ONTO IPAQ *** + copy geocache.psp C:\"My Documents\Pocket_PC My Documents"\Incoming\Lafayette.psp + copy geocache.psp C:\"My Documents\Pocket_PC My Documents"\Incoming\BatonRouge.psp + copy geocache.psp C:\"My Documents\Pocket_PC My Documents"\Incoming\NewOrleans.psp + copy geocache.psp C:\"My Documents\Pocket_PC My Documents"\Incoming\Houston.psp + + o When I get my .loc files from geocaching.com, I stick them in the + "c:\makefiles" directory and run "makefiles.bat". when the batch + file is complete in a few seconds, I have managed to do accomplish + a few things that used to be some cumbersome they weren't even worth + doing: + + 1. I have a "Magellan Protocol" text file to load onto my Meridian's + SD card containing all of the geocaches from those 2 files. + + 2. I have created pushpins for 4 seperate maps. Since I'm putting them + in the "Pocket_PC My Documents\Incoming" folder, they will auto-sync + to my iPaq when it syncs. Since I store my maps on my iPaq's SD card, + I need to move these over to my maps folder by hand later. That takes + all of about 10 seconds. + + 3. It is my preference to have "synthesized shortnames" on my pushpin + files instead of geocaching.com "GCXXXX" names. Since the shortname + synthesizer for pushpins is set to around 32 bytes, instead of seeing + "GCF00D" as a pushpin name, I see "Swinging Rope Bridge." + diff --git a/psp.c b/psp.c index c8a752751..ea2e085ba 100644 --- a/psp.c +++ b/psp.c @@ -140,26 +140,88 @@ psp_fwrite_word(unsigned int x, FILE *fp) #endif -static int -valid_psp_header(char * header, int len) +/* Implement the grid in ascii art... This makes a bit of sense if you stand + on a point over the north pole and look down on the earth. + +-180 -90 0 90 180 +------------------------------------ /\ +| 0x03 U|S 0x02 U|k 0x00 | 0x01 | 90 +|--------|--------|--------|--------| 0 +| 0x07 | 0x06 | 0x04 | 0x05 | -90 +------------------------------------ \/ +*/ +static +char grid_byte(double lat, double lon) { - char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x00 }; /* 1niP */ - char *p, *s; - - if (len != 32) { - return (-1); + char c = 0x00; + + if ((lon >= 0.0) && (lon < 90.0)) { + if (lat >= 0.0) { + c = 0x00; + } else { + c = 0x04; + } + } else + if (lon >= 90.0) { + if (lat >= 0.0) { + c = 0x01; + } else { + c = 0x05; + } + } else + if ((lon < 0.0) && (lon >= -90.0)) { + if (lat >= 0.0) { + c = 0x02; + } else { + c = 0x06; + } + } else + if (lon < -90.0) { + if (lat >= 0.0) { + c = 0x03; + } else { + c = 0x07; + } } + + return (c); +} - p = header_bytes; - s = header; - - while (*p) { - if (*p++ != *s++) { - return(-1); - } +void decode_psp_coordinates(double * lat, double * lon, const char lonbyte) +{ + /* This is some sort of 1/2 Polar, 1/2 Cartesian coordinate mess in */ + /* the pin file. I really shouldn't have to do this. Zones 02 and 03 */ + /* work properly. The other zones are assumptions based on 02 and 03 */ + + if ((lonbyte == 0x02) || (lonbyte == 0x06)) { + /* one step west of zero longitude */ + if (*lon > 0.0) + *lon *= -1.0; + } else + if ((lonbyte == 0x03) || (lonbyte == 0x07)) { + /* two steps west of zero longitude */ + if (*lon > 0.0) + *lon -= 180.0; + } else + if ((lonbyte == 0x00) || (lonbyte == 0x04)) { + /* one step east of zero longitude */ + if (*lon < 0.0) + *lon *= -1.0; + } else + if ((lonbyte == 0x01) || (lonbyte == 0x05)) { + /* two steps east of zero longitude */ + if (*lon < 0.0) + *lon += 180.0; } +} + +static int +valid_psp_header(char * header) +{ + char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50 }; /* 1niP */ - return (0); + return (memcmp(header_bytes, header, 4)); + } static char * @@ -213,14 +275,17 @@ psp_read(void) { char buff[MAXPSPSTRINGSIZE + 1]; double radians; + double lat, lon; waypoint *wpt_tmp; int stringsize; short int pincount; + short int pindex; + char gridbyte = 0x00; /* 32 bytes - file header */ psp_fread(&buff[0], 1, 32, psp_file_in); - if (valid_psp_header(buff, 32) != 0) { + if (valid_psp_header(buff) != 0) { fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n"); } @@ -229,41 +294,44 @@ psp_read(void) while (pincount--) { wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); - /* things we will probably never know about this waypoint */ - /* coming from a pushpin file. */ - - /* - wpt_tmp->creation_time; - wpt_tmp->position.altitude.altitude_meters; - wpt_tmp->url; - wpt_tmp->url_link_text; - wpt_tmp->icon_descr; TODO: map this. - */ + wpt_tmp->position.altitude.altitude_meters = unknown_alt; + + /* offset 0x20 - 0x21 pin index */ + psp_fread(&pindex, 1, 2, psp_file_in); - /* 4 bytes at start of record */ - /* coming out of S&T, this 1st byte is probably the pin # (0x01, 0x02, etc...) */ - /* coming from pocketstreets, it's generally 0x00. Sometimes 0xC3. ? */ + /* offset 0x22 - 0x23 */ + psp_fread(&buff[0], 1, 2, psp_file_in); - psp_fread(&buff[0], 1, 4, psp_file_in); - - /* 1 byte, unkown */ - psp_fread(&buff[0], 1, 1, psp_file_in); + /* offset 0x24 */ + /* 1 byte, the grid byte - needed for sign corrections later*/ + psp_fread(&gridbyte, 1, 1, psp_file_in); /* 8 bytes - latitude in radians */ radians = psp_fread_double(psp_file_in); - wpt_tmp->position.latitude.degrees = (radians * 180.0) / M_PI; + lat = (radians * 180.0) / M_PI; /* 8 bytes - longitude in radians */ radians = psp_fread_double(psp_file_in); - wpt_tmp->position.longitude.degrees = (radians * 180.0) / M_PI; + lon = (radians * 180.0) / M_PI; + + /* since we don't know the origin of this PSP file, we use */ + /* the grid byte adjust longitude, if necessary, mimicing */ + /* the behavior of pocketstreets correcting the data. This */ + /* does not correct the fact that points in eastern US are */ + /* written with the wrong coordinates by S&T. (MS bug) */ + decode_psp_coordinates(&lat, &lon, gridbyte); + + wpt_tmp->position.latitude.degrees = lat; + wpt_tmp->position.longitude.degrees = lon; + /* 1 byte - pin display properties */ psp_fread(&buff[0], 1, 1, psp_file_in); /* 3 bytes - unknown */ psp_fread(&buff[0], 1, 3, psp_file_in); - /* 1 bytes - icon 0x00 - 0x27 */ + /* 1 bytes - icon (values: 0x00 - 0x27) */ psp_fread(&buff[0], 1, 1, psp_file_in); /* 3 bytes - unknown */ @@ -329,6 +397,7 @@ psp_waypt_pr(const waypoint *wpt) char tbuf[64]; char c; int i; + static short int pindex = 0; char *shortname; char *description; @@ -359,16 +428,28 @@ psp_waypt_pr(const waypoint *wpt) /* convert lat/long back to radians */ lat = (wpt->position.latitude.degrees * M_PI) / 180.0; lon = (wpt->position.longitude.degrees * M_PI) / 180.0; - - /* 4 leading bytes */ + + pindex++; + le_write16(tbuf, pindex); + /* 2 bytes - pin index */ + fwrite(tbuf, 1, 2, psp_file_out); + + /* 2 bytes - null bytes */ memset(tbuf, '\0', sizeof(tbuf)); - fwrite(tbuf, 1, 4, psp_file_out); - - /* my test files seem to always have this byte as 0x03, */ - /* although nothing seems to really care. */ - c = 0x03; + fwrite(tbuf, 1, 2, psp_file_out); + - /* 1 unknown bytes */ + /* set the grid byte */ + c = grid_byte(wpt->position.latitude.degrees, + wpt->position.longitude.degrees); + + /* since the grid byte matches with what pocketstreets does to */ + /* input files, our output appears identical to a pin file that */ + /* has already been processed and corrected by pocketstreets. */ + /* Due to the grid and signs, it'll look different than one that */ + /* comes straight from S&T. */ + + /* the grid byte */ fwrite(&c, 1, 1, psp_file_out); /* 8 bytes - latitude/radians */ @@ -378,7 +459,7 @@ psp_waypt_pr(const waypoint *wpt) psp_fwrite_double(lon, psp_file_out); /* 1 byte - pin properties */ - c = 0x14; /* display pin name on! display notes on! */ + c = 0x14; /* display pin name on, display notes on. 0x04 = no notes */ fwrite(&c, 1, 1, psp_file_out); memset(tbuf, '\0', sizeof(tbuf)); diff --git a/reference/ps.psp b/reference/ps.psp index 4685ec58f774f8ea4d212d519374d58634cce568..d37c83e719a33a3477a458b00bc02a2d558acf6a 100644 GIT binary patch delta 93 zcmX@YeuRC30xKf}0|V1U)l^m{Frz<}l^M+VnaIilVoZ)_3}|j